﻿-------------------------------------------------------------------------------
--[[

TODO:
	- joined: HH:mm  - make so its servertime
]]--
-------------------------------------------------------------------------------

--Initial values for some general globals

DKPMS = LibStub("AceAddon-3.0"):NewAddon("DKPManager Server", "AceConsole-3.0","AceEvent-3.0","AceTimer-3.0")

-- Name of the player running the this instance of the server
zKP_Server_Player_name = "";


-- Default DKP start bonus awarded to any plyer currently a member of the raid, not Waitinglist
zKP_StartBonus = 0;

-- Default DKP end bonus awarded to any player currently a member of the raid, not Waitinglist
zKP_EndBonus = 0;

-- Used for deciding if a raid is ongoing or not. True = ongoing  ; False = Stopped
zKP_raid_running = false;

-- Do not touch this variable unless you know what it does - Essentially it is used for debug data to be printed.
zKP_debugging = true;

-- Used as a prefix for whispers to members in waitinglist.
title_prefix = "zKP - ";

zKP_WaitListInterval = 600; -- time between waitinglist checks equal to 10min's in seconds
zKP_WaitListResponseTime = 60; -- time between a waitinglist response has been send and the player should respond in seconds.

zKP_UpdateInterval = nil
zKP_frequentDKP = nil

older_than_days = 30; -- Timeframe in days of when old raids shall be removed.

-- ACE3 library setup



-- ?
ResetTimers = false;

DKPMS.RaidUpdateInterval = nil
DKPMS.WaitingListTimer	 = nil



AllRealmsDKPData = {}
AllRealmsDKPData["Arathor"] = {}

RaidPlayerNames = {};

AltList = {}
me = "Timbo"; --UnitName("player");

itemID = "item:%d:0:0:0:0:0:0:0";

--dataarray = {};  --Used to display the entire list
numEntries=0;
ListingValue = "DKP";

--------------CommandHandlers------------

function DKPMS:OnInitialize()

    local frame = getglobal("DKPManager")
    if(frame) then
		tinsert(UISpecialFrames, frame)	  
	end

    zKP_Server_Player_name, realm = UnitName("player");	


	if(not AllRealmsDKPData["Arathor"]) then
		AllRealmsDKPData["Arathor"] = {};

		DKPData = AllRealmsDKPData["Arathor"]
		if(not DKPData[me]) then 
			DKPData[me] = {update_Value = 1};
		end        
	else
		DKPData = AllRealmsDKPData["Arathor"]
		if(not DKPData[me]) then 
			DKPData[me] = {update_Value = 1};
		end        
	end

	if(BidHistory==nil) then
		BidHistory = {};
	end
	
	if(PreviusRaid == nil) then 
	   PreviusRaid = {}; 
	end

	if not ( zKP_options) then	
		zKP_options = {}
	end

	if not (zKP_options.UpdateInterval) then
		zKP_options.UpdateInterval = 1;
	end

	if not ( zKP_options.frequentDKP ) then	
		zKP_options.frequentDKP = 1;
	end

	if(zUserClasses==nil) then
		zUserClasses = {}; --list of what player is what class
	end

	zKP_UpdateInterval = zKP_options.UpdateInterval * 60

	if (CurrentRaid.Status == "Running") then	
		DKPMS.RaidUpdateInterval = DKPMS:ScheduleRepeatingTimer("OnUpdate_AddRaidDKP", zKP_UpdateInterval)
		DKPMS.WaitingListTimer	 = DKPMS:ScheduleRepeatingTimer("OnUpdate_RunCheckWaitList", zKP_WaitListInterval)
		DKPMS:Print("Raid in last session was not properly ended, raid continued and timers started.")
		DKPMS:Print("Current Raid: ")
		DKPMS:Print("          DKP@RaidLenght: "..CurrentRaid.EarnedDKP.Zmax)
		DKPMS:Print("          Status: "..CurrentRaid.Status)
		
        local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP["Zmax"], "(.+)@(.+)")
        getglobal("DKPManagerMainFrameRaidDkpLabel"):SetText("Raid DKP: "..s_dkp)
		getglobal("DKPManagerMainFrameRaidStatusLabel"):SetText("Raid running")
		zKP_raid_running = true
		getglobal("DKPManagerMainFrame"):Show()
	end

	
	-- Loads the addons options
	DKPMSopt:LoadOptions()
	DKPMS:RegisterChatCommand("start", "StartRaid")
	DKPMS:RegisterChatCommand("stop" , "EndRaid")
	DKPMS:RegisterChatCommand("resume", "ResumeRaid")
	DKPMS:RegisterChatCommand("pause", "PauseRaid")
	DKPMS:RegisterChatCommand("dkpm", "DKPManager_SlashCommandHandler")
	DKPMS:RegisterChatCommand("dkpmanager", "DKPManager_SlashCommandHandler")
	DKPMS:RegisterChatCommand("ld", "LootDecider_SlashCommandHandler")
	DKPMS:RegisterChatCommand("loot", "LootDecider_SlashCommandHandler")
	DKPMS:RegisterChatCommand("lootdecider", "LootDecider_SlashCommandHandler")
		
	DKPMS:RegisterEvent("RAID_ROSTER_UPDATE", "HiddenOnEvent")
	DKPMS:RegisterEvent("CHAT_MSG_ADDON","DkpQueryHandler")
	DKPMS:RegisterEvent("CHAT_MSG_WHISPER","DkpQueryHandler")
	DKPMS:RegisterEvent("CHAT_MSG_WHISPER_INFORM","DkpQueryHandler")

	DKPMS:RegisterEvent("CHAT_MSG_SYSTEM", "HiddenOnEvent")


	DKPMSld:InitializeLootDecider()

end

function DKPMS:OnEnable()	
end

function DKPMS:OnDisable()	
end


--------------- COMMAND HANDLERS ------------------
function DKPMS:DKPManager_SlashCommandHandler(msg)    
	getglobal("DKPManagerMainFrame"):Show();
end

function DKPMS:DKPManager_SlashCommandHandler_dkm()
end

function DKPMS:LootDecider_SlashCommandHandler(msg)
	DKPMSld:LootDecider_SlashCommandHandler(msg)
end	



------------- FILTERS -----------------

function myChat_MSG_WHISPER_Filter(msg)
  
  if ( string.find(string.lower(msg), "^bid.+") ~= nil) then
    return true
  end

  if ( string.find(string.lower(msg), "^dkp$") ~= nil) then
    return true
  end
  
  if ( string.find(string.lower(msg), "^dkp %a+") ~= nil) then
    return true
  end

  if (string.find(string.lower(msg), "^wl$") ~= nil) then
    return true
  end
  
  if (string.find(string.lower(msg), "^wl.+") ~= nil) then
    return true
  end
  
 if ( string.find(string.lower(msg), "^<zkp>.+") ~= nil) then
    if (arg2 ~= arg5) then
        return true
    end  
 end
  
end

function myChat_MSG_WHISPER_INFORM_Filter(msg)
  if ( string.find(string.lower(msg), "^<zkp>.+") ~= nil) then
        return true
  end  
end

ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER", myChat_MSG_WHISPER_Filter);	
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", myChat_MSG_WHISPER_INFORM_Filter);



----------- Misc Functions START ---------------


function DKPMS:Debug(text)
    if (zKP_debugging == true) then 
        DKPMS:Print("[DEBUG] "..text);
    end
end

function DKPMS:Trim (s)
	return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end

----------- Misc Functions END ---------------

function DKPMS:FixName(name)

    if(name==nil) then
        return
    end
	local real_name = name;
	real_name = DKPMS:Trim(real_name);
	real_name = string.lower(real_name);
	real_name = string.upper(string.sub(real_name,1,1))..string.sub(real_name,2);
	return real_name
end

function DKPMS:UserInRaid(who)

	local numRaidMembers = GetNumRaidMembers();

	for i=1, numRaidMembers do 
	local name, rank, subgroup, level, class, filename, zone, online = GetRaidRosterInfo(i);

		if string.lower(name)==string.lower(who) then 
			return true
		
		end
	end
	return false
	
end

function DKPMS:AwardRaid(dkp,raidtime)    
		local counter = 0;
		local numRaidMembers = GetNumRaidMembers();

		  for i=1, numRaidMembers do 
		  local name, rank, subgroup, level, class, filename, zone, online = GetRaidRosterInfo(i);

			if name then 
				if (online) then
				--Check if its an Alt of someone
				if(AltList[name]) then
					--If it is an alt, be sure to add to the main of that alt
					name = AltList[name];
				end	


					if (CurrentRaid.EarnedDKP[name]==nil) then 
						CurrentRaid.EarnedDKP[name] = dkp.."@"..raidtime; 
					else
						local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP[name], "(.+)@(.+)");
						CurrentRaid.EarnedDKP[name] = (tonumber(s_dkp)+dkp).."@"..(tonumber(s_raidtime)+raidtime); 
					end
					counter = counter+1;
				end
			end
		  end

		local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP["Zmax"], "(.+)@(.+)");

		CurrentRaid.EarnedDKP["Zmax"] = (tonumber(s_dkp)+dkp).."@"..(tonumber(s_raidtime)+raidtime); 
        local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP["Zmax"], "(.+)@(.+)");
        getglobal("DKPManagerMainFrameRaidDkpLabel"):SetText("Raid DKP: "..s_dkp);
  
  return counter;
end

function DKPMS:RollBackRaidDKP()
	if (CurrentRaid.Status == "Stopped") then			
		if (PreviusRaid[tostring(date("%Y%m%d",time()))] ~= nil) then			
			for player,value in pairs(PreviusRaid[tostring(date("%Y%m%d",time()))].EarnedDKP) do		
				local _, _, s_dkp, s_raidtime = string.find(value, "(.+)@(.+)")				
				s_dkp = tonumber(s_dkp) - (2*tonumber(s_dkp)) --Reverses the amount to a negativ as big as the positive amount awarded			
				DKPMS:ChangeValue(player,s_dkp)			

				PreviusRaid[tostring(date("%Y%m%d",time()))].EarnedDKP[player] = "0@0"
				
				if (PreviusRaid[tostring(date("%Y%m%d",time()))].WaitList[player]) then	
					PreviusRaid[tostring(date("%Y%m%d",time()))].WaitList[player] = "0@0"
					DKPMS:Print("player: "..player.." EarnedDKP = "..PreviusRaid[tostring(date("%Y%m%d",time()))].EarnedDKP[player].." WaitList = "..PreviusRaid[tostring(date("%Y%m%d",time()))].WaitList[player])
				end
				
			end
		end
	end
end

-- ADJUSTS THE CURRENT RUNNING RAIDS DKP ACCORDING THE LENGHT PROVIDED
function DKPMS:AdjustRaidDkp(lenght)

	if (CurrentRaid.Status == "Running" or CurrentRaid.Status == "Paused") then	
			DKPMS:AwardRaid(lenght,lenght)

			for player,value in pairs(CurrentRaid.WaitList) do		
				local _, _, s_dkp, s_raidtime = string.find(value, "(.+)@(.+)")
				s_dkp = tonumber(s_dkp) + tonumber(lenght)
				s_raidtime = tonumber(s_raidtime) + tonumber(lenght)

				if (s_dkp < 0) then	
					s_dkp = 0
				end

				if (s_raidtime < 0) then	
					s_raidtime = 0
				end

				if (DKPMS:IsPlayerOnline(player)) then	
					CurrentRaid.WaitList[player] = s_dkp.."@"..s_raidtime

				end
			end		
	else
		DKPMS:Warning("A raid must be running \nin order to use this option.")
	end
end

-- Creates a cancelled raid with the amount of updates parsed in the parameter modifier
function DKPMS:CreateCancelledRaid(modifier)
	if (CurrentRaid.Status == "Stopped" and DKPMS:IsDkpLeaderMasterLooter() == true) then	
		DKPMS:RollBackRaidDKP()
		DKPMS:StartRaid() -- Starts a new raid
		DKPMS:AwardRaid(modifier,modifier) -- Awards the raid with DKP

		for player,value in pairs(CurrentRaid.WaitList) do		
			local _, _, s_dkp, s_raidtime = string.find(value, "(.+)@(.+)")
			s_dkp = tonumber(s_dkp) + tonumber(modifier)
			s_raidtime = tonumber(s_raidtime) + tonumber(modifier)

			if (s_dkp < 0) then	
				s_dkp = 0
			end

			if (s_raidtime < 0) then	
				s_raidtime = 0
			end

			if (DKPMS:IsPlayerOnline(player)) then	
				CurrentRaid.WaitList[player] = s_dkp.."@"..s_raidtime

			end
		end		

		DKPMS:EndRaid() -- Ends the raid and calculates DKP

		if (PreviusRaid[tostring(date("%Y%m%d",time()))] ~= nil) then	
			for player,value in pairs(PreviusRaid[tostring(date("%Y%m%d",time()))].EarnedDKP) do					
				if (PreviusRaid[tostring(date("%Y%m%d",time()))].WaitList[player]) then	
					PreviusRaid[tostring(date("%Y%m%d",time()))].WaitList[player] = PreviusRaid[tostring(date("%Y%m%d",time()))].EarnedDKP[player]
				end
			end				
		end
		DKPMSopt:SetRaidLength(0)
		DKPMS:Print("Canceled raid created and DKP+Attendance awarded to members") 		
	else									
		DKPMS:Warning("A raid is already running\nStop the running raid and try again")
	end
end

function DKPMS:AwardRaidUser(name,dkp,raidtime)
	if name then 
	name = DKPMS:Trim(name);
		--Check if its an Alt of someone
		if(AltList[name]) then
			--If it is an alt, be sure to add to the main of that alt
			whichplayer = AltList[name];
		end	


			if (CurrentRaid.EarnedDKP[name]==nil) then 
				CurrentRaid.EarnedDKP[name] = dkp.."@"..raidtime; 
			else

				local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP[name], "(.+)@(.+)");
				
				CurrentRaid.EarnedDKP[name] = (tonumber(s_dkp)+dkp).."@"..(tonumber(s_raidtime)+raidtime); 


			end

		return true

	end
	return false
end

function DKPMS:RemoveOldRaids()
    
	local data = {};
    
	for raid_date,raidarray in pairs(PreviusRaid) do
		data = {};
        
		data["year"] = string.sub(raid_date,0,4);
		data["month"] = string.sub(raid_date,5,6);
		data["day"] = string.sub(raid_date,7,8);

        if(time(data)<time()-(older_than_days*86400)) then
		DEFAULT_CHAT_FRAME:AddMessage("Raid-id: "..raid_date.." is older than "..older_than_days.." days, deleting it");
		
        PreviusRaid[raid_date] = nil;
        
		end
        
	end	
end

function DKPMS:Warning(message)
        getglobal("zKP_ServerMessageFormLabelText"):SetText(message);
        getglobal("zKP_ServerMessageForm"):Show();	
end

function DKPMS:StartRaid()    
    if ( DKPMS:IsDkpLeaderMasterLooter()) then
		if (CurrentRaid.Status == "Stopped") then	
			DKPMS.RaidUpdateInterval = DKPMS:ScheduleRepeatingTimer("OnUpdate_AddRaidDKP", zKP_UpdateInterval)
			DKPMS.WaitingListTimer	 = DKPMS:ScheduleRepeatingTimer("OnUpdate_RunCheckWaitList", zKP_WaitListInterval)

			CurrentRaid = {};
			CurrentRaid.EarnedDKP = {};
			CurrentRaid.WaitList = {};
		
			CurrentRaid.WaitListLastChecked = {};
		
			CurrentRaid.WaitListLastPassed = {};
		
			CurrentRaid.JoinedWaitList = {};
		
			CurrentRaid.Status = "Running";
		
			CurrentRaid.EarnedDKP["Zmax"] = "0@0";
		
			numbers_in_raid = 0;
			
			DKPMS:RemoveOldRaids(); --removes old raids, defined at top
		
			SendChatMessage("Raid has started. You will recieve "..zKP_options.frequentDKP.."dkp every "..zKP_options.UpdateInterval.." minute", "RAID", nil, nil);
			if ( zKP_debugging == false ) then 
				SendChatMessage("Raid has started. Whisper me 'WL' to join waitlist", "GUILD", nil, nil);
			end
			
			SendAddonMessage("zKP_Server", "DkpLeader", "GUILD",nil);
			

			zKP_raid_running = true;
			getglobal("DKPManagerMainFrameRaidStatusLabel"):SetText("Raid running");			
		else
			DKPMS:Warning("Raid already Running")
		end
    else
        getglobal("zKP_ServerMessageFormLabelText"):SetText("Need Master Lood privileges");
        getglobal("zKP_ServerMessageForm"):Show();    
    end
end

function DKPMS:SpecialPlusMethod(line,line2)

	local _, _, s_dkp, s_raidtime = string.find(line, "(.+)@(.+)");
	local _, _, s_dkp2, s_raidtime2 = string.find(line2, "(.+)@(.+)");
					
	return DKPMS:Round(tonumber(s_dkp)+tonumber(s_dkp2)).."@"..DKPMS:Round(tonumber(s_raidtime)+tonumber(s_raidtime2)); 
	
end

function DKPMS:EndRaid()
    if (DKPMS:IsDkpLeaderMasterLooter() ) then    
		if (CurrentRaid.Status == "Running") then	

			zKP_raid_running = false;
			
			if (type(DKPMS.RaidUpdateInterval) ~= "nil") then	
				DKPMS:CancelTimer(DKPMS.RaidUpdateInterval) 
			end
			if (type(DKPMS.WaitingListTimer) ~= "nil") then	
				DKPMS:CancelTimer(DKPMS.WaitingListTimer)	 
			end
		
			local end_bonus = nil;

			if(PreviusRaid==nil) then
				PreviusRaid = {};
				
			end
			
			local raidStamp = date("%Y%m%d",time());
			
			if(PreviusRaid[raidStamp]==nil) then

				PreviusRaid[raidStamp] = {};
		
				PreviusRaid[raidStamp].EarnedDKP = {};
				PreviusRaid[raidStamp].WaitList = {};
				PreviusRaid[raidStamp].JoinedWaitList = {};
			
			end
			
			
			for s_player,s_data in pairs(CurrentRaid.WaitList) do --move the dkp from waitlist to the raid. since they should get some dkp also. He will also recieve endbonus

				local _, _, w_dkp, w_raidtime = string.find(s_data, "^(.+)@(.+)$");
			
					if (CurrentRaid.EarnedDKP[s_player]==nil) then
						CurrentRaid.EarnedDKP[s_player] = DKPMS:Round(tonumber(w_dkp)).."@"..DKPMS:Round(tonumber(w_raidtime)); 

					else
		
						local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP[s_player], "(.+)@(.+)");
								
						CurrentRaid.EarnedDKP[s_player] = DKPMS:Round(tonumber(s_dkp)+tonumber(w_dkp)).."@"..DKPMS:Round(tonumber(s_raidtime)+tonumber(w_raidtime)); 
					end
			end
		
			
		
			if(zKP_EndBonus ~= 0) then 
				if(zKP_EndBonus > 0) then 
					DKPMS:AwardRaid(zKP_EndBonus, 0)
					SendChatMessage("Raid has ended. Everyone have been awarded a "..zKP_EndBonus.."dkp endbonus", "RAID", nil, nil);
					end_bonus = 1;
					zKP_options.EndBonus = zKP_EndBonus; 
				end
			end
			
			if(end_bonus==nil) then
				end_bonus = 0; 
			end
		
			for player,value in pairs(CurrentRaid.EarnedDKP) do
			
				local newDKP = DKPMS:ChangeValue(player,value);
			
				if(PreviusRaid[raidStamp].EarnedDKP[player]==nil) then
					PreviusRaid[raidStamp].EarnedDKP[player] = value;
				else
					PreviusRaid[raidStamp].EarnedDKP[player] = DKPMS:SpecialPlusMethod(PreviusRaid[raidStamp].EarnedDKP[player],value);
					
				end

				if(player ~= "Zmax") then
					local _, _, newValue, s_raidtime = string.find(value, "(.+)@(.+)");
					if(newValue~=nil and newDKP~=nil) then
						SendChatMessage("<zKP>Raid is now closed. you earned "..newValue.." DKP, total: "..newDKP, WHISPER, nil, player);
						CurrentRaid.EarnedDKP[player] = nil;
		
					end
				end		
			end
			
			
			for wPlayer,wValue in pairs(CurrentRaid.WaitList) do
				if(wValue~=nil and wPlayer~=nil) then
		
					if(PreviusRaid[raidStamp].WaitList[wPlayer]==nil) then
						PreviusRaid[raidStamp].WaitList[wPlayer] = wValue;-- DKPMS:Print("line 481");
					else
						PreviusRaid[raidStamp].WaitList[wPlayer] = DKPMS:SpecialPlusMethod(PreviusRaid[raidStamp].WaitList[wPlayer],wValue);
					end
		
					CurrentRaid.WaitList[wPlayer] = nil;
				end
			end
		
			for jwPlayer,jwValue in pairs(CurrentRaid.JoinedWaitList) do
				if(jwValue ~=nil and jwPlayer ~=nil) then
					PreviusRaid[raidStamp].JoinedWaitList[jwPlayer] = v;
					CurrentRaid.JoinedWaitList[jwPlayer] = nil;
				end
			end

			getglobal("DKPManagerMainFrameRaidStatusLabel"):SetText("Raid ended");
			CurrentRaid.Status = "Stopped";
		else
			DKPMS:Warning("Raid not started \nor\n Raid is paused")
		end
    else
		DKPMS:Warning("Need Master Lood privileges")
    end 
end

function DKPMS:PauseRaid()
    if ( DKPMS:IsDkpLeaderMasterLooter() ) then
		if (CurrentRaid.Status == "Running") then	
			
			zKP_raid_running = false;
			
			DKPMS:CancelTimer(DKPMS.RaidUpdateInterval) 
				DKPMS.RaidUpdateInterval = nil
			DKPMS:CancelTimer(DKPMS.WaitingListTimer)	 
				DKPMS.WaitingListTimer = nil
			
			CurrentRaid.Status = "Paused";
			getglobal("DKPManagerMainFrameRaidStatusLabel"):SetText("Raid "..CurrentRaid.Status);
			SendChatMessage("Raid has temporarily been "..CurrentRaid.Status,"RAID",nil,nil);
		else
			DKPMS:Warning("Raid not started")
		end
    else
		DKPMS:Warning("Need Master Lood privileges")
	end 
end

function DKPMS:ResumeRaid()       
    if ( DKPMS:IsDkpLeaderMasterLooter() ) then
		if (CurrentRaid.Status == "Paused") then	
			
			zKP_raid_running = true;
		
			DKPMS.RaidUpdateInterval = DKPMS:ScheduleRepeatingTimer("OnUpdate_AddRaidDKP", zKP_UpdateInterval)
			DKPMS.WaitingListTimer	 = DKPMS:ScheduleRepeatingTimer("OnUpdate_RunCheckWaitList", zKP_WaitListInterval)


			SendChatMessage("Raid is "..CurrentRaid.Status.." again","RAID",nil,nil);
		
			local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP["Zmax"], "(.+)@(.+)");
		
			if(s_dkp~=nil) then
				SendChatMessage(s_dkp.."dkp over "..s_raidtime.." minutes","RAID",nil,nil);
			end
			CurrentRaid.Status = "Running";
			getglobal("DKPManagerMainFrameRaidStatusLabel"):SetText("Raid "..CurrentRaid.Status);
		else
			DKPMS:Warning("Raid is not paused\nor\nRaid not started")
		end
    else
		DKPMS:Warning("Need Master Lood privileges")
    end 
end

function DKPMS:Round(number)

	return tonumber(string.format("%.0f",tonumber(number)));
	
end

function DKPMS:CheckWaitlist()

	if (CurrentRaid.WaitListLastChecked==nil) then
		CurrentRaid.WaitListLastChecked = {};
	end
	
	local listoplays = "";

	for s_player,s_info in pairs(CurrentRaid.WaitList) do

		local LoggedOnPlayer = DKPMS:IsPlayerOnline(s_player)

		if(LoggedOnPlayer~=nil) then

			SendChatMessage("<zKP>whisper me the following: wl accept", "WHISPER", nil, LoggedOnPlayer);

			listoplays = listoplays..", "..LoggedOnPlayer;

			if(s_player~=LoggedOnPlayer) then
				SendChatMessage("<zKP>whisper me the following: wl accept", "WHISPER", nil, s_player);
				listoplays = listoplays..", "..s_player;
			end

			CurrentRaid.WaitListLastChecked[s_player] = time(); --last/this successfully checked

		end
	end
end

function DKPMS:OnUpdate_AddRaidDKP()
	DKPMS:AwardRaid(tonumber(zKP_options.frequentDKP),tonumber(zKP_options.UpdateInterval)); 
end

function DKPMS:OnUpdate_RunCheckWaitList()
	DKPMS:CheckWaitlist();
end

function DKPMS:HiddenOnEvent(event)
	if(GetNumRaidMembers()>0) then
		numbers_in_raid = 0;
			if(zKP_raid_running) then
				if(event == "RAID_ROSTER_UPDATE") then
					DKPMS:Debug(""..event)
					if (GetNumRaidMembers() ~= numbers_in_raid) then --if it changed
						numbers_in_raid = GetNumRaidMembers();

						  for i=1, numbers_in_raid do 
						  local name, rank, subgroup, level, class, filename, zone, online = GetRaidRosterInfo(i);

							if name then 

								--Check if its an Alt of someone
								if(AltList[name]) then
									--If it is an alt, be sure to add to the main of that alt
									name = AltList[name];
								end	


								if (CurrentRaid.EarnedDKP[name]==nil) then --if new to raid

									if(CurrentRaid.WaitList[name]~=nil) then
										
										local _, _, w_dkp, w_raidtime = string.find(CurrentRaid.WaitList[name], "^(.+)@(.+)$");
										if(CurrentRaid.EarnedDKP[name]==nil) then
											CurrentRaid.EarnedDKP[name] = DKPMS:Round(tonumber(w_dkp)).."@"..DKPMS:Round(tonumber(w_raidtime)); --waitlist to raid
										end

										local hours,minutes = GetGameTime();
										DEFAULT_CHAT_FRAME:AddMessage(hours..":"..minutes..": "..name.." joined in from waitlist, moved to raid with "..CurrentRaid.WaitList[name].."dkp");



										CurrentRaid.WaitList[name] = nil;
									else
									CurrentRaid.EarnedDKP[name] = "0@0";

									end

								else
									if(CurrentRaid.WaitList[name]~=nil) then
										local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.EarnedDKP[name], "^(.+)@(.+)$");
										local _, _, w_dkp, w_raidtime = string.find(CurrentRaid.WaitList[name], "^(.+)@(.+)$");

										CurrentRaid.EarnedDKP[name] = (tonumber(s_dkp)+DKPMS:Round(tonumber(w_dkp))).."@"..(tonumber(s_raidtime)+DKPMS:Round(tonumber(w_raidtime))); --waitlist to raid
										local hours,minutes = GetGameTime();
										DEFAULT_CHAT_FRAME:AddMessage(hours..":"..minutes..": "..name.." joined in from waitlist, moved to raid with "..CurrentRaid.WaitList[name].."dkp. Player been in raid before.");
										CurrentRaid.WaitList[name] = nil;
									end

								end

								if(zUserClasses[name]==nil) then
									zUserClasses[name] = class; 

								end



							end
						  end
					end
				end
	
				if(event == "CHAT_MSG_SYSTEM") then
					if(string.find(arg1, "^.+ has gone offline") or string.find(arg1, "^.+ has come online" )) then
						DKPMS:Print("updating guildroster");
						GuildRoster();
					end
				end					
		end
	end
end

function DKPMS:AddToHistory(player,amount,time,itemID,itemName)

		local whichplayer = player;
		local line = "";
		whichplayer = string.lower(whichplayer);
		whichplayer = string.upper(string.sub(whichplayer,1,1))..string.sub(whichplayer,2);

		local amount = amount;
		if(amount == "") then
			amount = 0;
		else
			amount = tonumber(amount);
		end

			--Check if its an Alt of someone
			if(AltList[whichplayer]) then
				--If it is an alt, be sure to add to the main of that alt
				whichplayer = whichplayer.."("..AltList[whichplayer]..")";
			end

			line = time.."@"..whichplayer.."@"..itemID.."@"..itemName.."@"..amount.."@"..GetZoneText();
			--example: "1186345000@Disenchant@30023@Totem of the Maelstrom@0@Serpentshrine Cavern", 
			
	
			table.insert(BidHistory,line);		
end

function DKPMS:GetGuildData()

 local numGuildMembers = GetNumGuildMembers();
 local name, level, class, zone, group, online, note, officernote;
	
	 for	i=1, numGuildMembers  do
		note = ""; officernote = "";
		name, rank, rankIndex, level, class, zone, group, note, officernote, online = GetGuildRosterInfo(i);
		
			if(rank=="Member" or rank=="Class Leader" or rank=="Officer" or rank=="Trial Member") then
				zUserClasses[name] = class; --add classes;
				DKPMS:Print(name.."("..class..") "..note);
			end

	end	
end

function DKPMS:IsPlayerOnline(s_player)
    
	local AllAlts = {};

	table.insert(AllAlts,s_player); --add player to first spot

	local all_alts_text = s_player;

	for a_alt,a_main in pairs(AltList) do
		if(string.lower(a_main)==string.lower(s_player)) then
			table.insert(AllAlts,a_alt);
			all_alts_text = all_alts_text.."@"..a_alt;
		end

	end



    local numGuildMembers = GetNumGuildMembers();
    local name, level, class, zone, group, online, note, officernote;

	 for	i=1, numGuildMembers  do
		name, rank, rankIndex, level, class, zone, group, note, officernote, online = GetGuildRosterInfo(i);
	end	

	 for	i=1, numGuildMembers  do
		note = ""; officernote = "";
		name, rank, rankIndex, level, class, zone, group, note, officernote, online = GetGuildRosterInfo(i);
			for id,a_name in pairs(AllAlts) do
				if(string.lower(a_name)==string.lower(name) and online) then
					return name;
				end
			end

	end	
	return nil;

end

--Called when the accept button is clicked...buttonname will include the tab of the button
--  in its name
function DKPMS:ChangeValue(player,savedAmount)

	local whichplayer = player;

	local hasTime = 0;
	whichplayer = string.lower(whichplayer);

	whichplayer = string.upper(string.sub(whichplayer,1,1))..string.sub(whichplayer,2);		

	local amount = savedAmount;

	if ( string.find(amount, "^(.+)@(.+)$") ) then

		local _, _, s_dkp, s_raidtime = string.find(amount, "^(.+)@(.+)$");

		amount = s_dkp;
		
		hasTime = s_raidtime;
	end


	if(amount == "") then

		amount = 0;
	else
		amount = tonumber(amount);
	end

	local mydata=DKPData[me];

	if(mydata.update_Value == nil) then
        mydata.update_Value = 1;
	end

	local newUpdateValue = mydata.update_Value;

	if(amount > 0) then

		newUpdateValue = mydata.update_Value + 1;
	end

	--Check if its an Alt of someone
	if(AltList[whichplayer]) then
		--If it is an alt, be sure to add to the main of that alt
		whichplayer = AltList[whichplayer];
	end

	if(mydata[whichplayer]==nil) then
		mydata[whichplayer] = {};
		mydata[whichplayer].DKP = 0;
		mydata[whichplayer].update_Value = 0;
		mydata[whichplayer].time = 0;
	end

	if(mydata[whichplayer].time==nil) then		
		mydata[whichplayer].time = 0;
	end
	

	if(mydata[whichplayer]) then			
		mydata[whichplayer].DKP = mydata[whichplayer].DKP + amount;
		mydata[whichplayer].update_Value = newUpdateValue;

		mydata[whichplayer].time = tonumber(mydata[whichplayer].time) + tonumber(hasTime);

		mydata.update_Value = newUpdateValue;

		return mydata[whichplayer].DKP;
	else
		DKPMS:Print(whichplayer.." not found");
	end
end

function DKPMS:DkpQueryHandler(event)

	if(event=="CHAT_MSG_WHISPER") then
		local whichplayer = arg2;


				--Check if its an Alt of someone
				if(AltList[whichplayer]) then
					--If it is an alt, be sure to add to the main of that alt
					whichplayer = AltList[whichplayer];
				end	

		------------------ [DKP] --------------------
		if( string.find(string.lower(arg1), "^dkp$") ~= nil ) then			   

			SendChatMessage("<zKP>"..whichplayer.." DKP:"..DKPMS:GetPlayerDKP(whichplayer)..". Attendance: "..DKPMS:GetPlayerAttendance(whichplayer).."%", WHISPER, nil, arg2);
			return;

		elseif(string.find(string.lower(arg1), "^dkp%s+(|cff.+)$")) then --when linking an item

				local _,_, link = string.find(arg1, "^dkp%s+(|cff.+)$");
				local printable = gsub(arg1, "\124", "\124\124");
                 zKPHiddenTooltip:ClearLines();
				 zKPHiddenTooltip:SetOwner(UIParent,"ANCHOR_NONE");

				 zKPHiddenTooltip:SetHyperlink(link);

				local classes = nil;

				for i=1,zKPHiddenTooltip:NumLines() do
					if(string.find(getglobal("zKPHiddenTooltipTextLeft"..i):GetText(), "^Classes: (.+)$")) then

					_,_,classes = string.find(getglobal("zKPHiddenTooltipTextLeft"..i):GetText(), "^Classes: (.+)$")
					end
				end

					if(classes~=nil) then
						local class_array = {};
						local i = 1;
						for class in string.gmatch(string.lower(classes),"(%a+)") do
							class_array[i] = class;
							i = i+1;
						end

						local output = "";
						local numRaidMembers = GetNumRaidMembers();
							for i=1, numRaidMembers do 
								local name, _, _, _, class, _, _, _ = GetRaidRosterInfo(i);
								
								for p,c in pairs(class_array) do
									if(string.lower(class)==c) then
									SendChatMessage("<zKP>"..name.."("..class..") "..DKPMS:GetPlayerDKP(name).."dkp", WHISPER, nil, arg2);
									end
								end
							end
						 zKPHiddenTooltip:Hide()
					end --classes~=nil
				return;
		elseif( string.find(string.lower(arg1), "^dkp ([^ ]*)$") ~= nil ) then	


			local _, _, check_player = string.find(string.lower(arg1), "^dkp ([^ ]*)$");

			if(check_player~=nil) then

				if(check_player=='warrior' or check_player=='warlock' or check_player=='druid' or check_player=='paladin' or
					check_player=='shaman' or check_player=='rogue' or check_player=='hunter' or check_player=='priest' or
					check_player=='mage' or check_player=="death knight") then --its class


					local outputArray = {};
					local thisClass = "Unknown";


					for i,v in DKPMSld:PairsByKeys(DKPData["Timbo"]) do	
						if(i~="update_Value") then	
							if(zUserClasses[i]~=nil) then
								if(string.lower(zUserClasses[i])==check_player) then
									outputArray[tonumber(v.DKP..math.random(1,9))] = i;
								end
							end
						end

					end

					for i,v in DKPMSld:PairsByKeys(outputArray,function(a,b) return b < a end) do	
						SendChatMessage("<zKP>"..string.sub(i,0,-2).." ("..DKPMS:GetPlayerAttendance(v).."%) - "..v, WHISPER, nil, arg2);
					end

					return;
				else

					check_player = string.lower(check_player);
					check_player = string.upper(string.sub(check_player,1,1))..string.sub(check_player,2);				

					-- Check if its an alt of a main, if so then overwrite the check_player with the main's name
					if(AltList[check_player]) then
						check_player = AltList[check_player];
					end	


					if(DKPData["Timbo"][check_player]~=nil) then
						SendChatMessage("<zKP>"..check_player.." DKP:"..DKPMS:GetPlayerDKP(check_player)..". Attendance: "..DKPMS:GetPlayerAttendance(check_player).."%", WHISPER, nil, arg2);
					else
						SendChatMessage("<zKP>"..check_player.." doesnt exist", WHISPER, nil, arg2);
					end
				end
			end
			return;
		------------------ [WAITLIST] --------------------
		elseif( string.find(string.lower(arg1), "^alt ([^ ]*)$") ~= nil ) then	

			local _, _, alt_name = string.find(arg1, "^alt ([^ ]*)$");


			alt_name = string.lower(alt_name);
			alt_name = string.upper(string.sub(alt_name,1,1))..string.sub(alt_name,2);



				--This if statement makes sure that no alt can be added as a main with an alt (ie alt loops)
				if(AltList[alt_name]) then
						SendChatMessage("<zKP>"..alt_name.." already registered to  "..AltList[alt_name], WHISPER, nil, arg2);
					
				else
						SendChatMessage("<zKP>"..alt_name.." is now "..whichplayer.."'s alt", WHISPER, nil, arg2);
						DKPMS:Print(alt_name.." is now "..whichplayer.."'s alt");
						AltList[alt_name] = whichplayer;
				end




			return;
		------------------ [WAITLIST] --------------------
		elseif( string.find(string.lower(arg1), "^wl$") ~= nil ) then		
			if(zKP_raid_running) then

				if(DKPMS:UserInRaid(whichplayer)==false) then --zng
					if(CurrentRaid.WaitList[whichplayer]==nil) then --if new waitlistplayer. add it
						CurrentRaid.WaitList[whichplayer] = "0@0";

						CurrentRaid.JoinedWaitList[whichplayer] = time();
						
						local hours,minutes = GetGameTime();
						DEFAULT_CHAT_FRAME:AddMessage(hours..":"..minutes..": "..whichplayer.." added to Waitlist");
                        

						SendChatMessage("<zKP>You have been added to waitlist", WHISPER, nil, arg2);

					end
				else
				SendChatMessage("<zKP>Already in raid you gnome!", WHISPER, nil, arg2);
				end
				
			else
				SendChatMessage("<zKP>No raid running", WHISPER, nil, arg2);
			end
			return;
		elseif( string.find(string.lower(arg1), "^wl ([^ ]*)$") ~= nil ) then	

			local _, _, this_command = string.find(arg1, "^wl ([^ ]*)$");
			local AllAlts = {};
			local LoggedOnPlayer = nil;
		
			if(debugging) then
			DEFAULT_CHAT_FRAME:AddMessage(this_command.." active ("..arg2..")");
			end

				if(string.lower(this_command)=="list") then
					local counter = 0;
					for i,v in pairs(CurrentRaid.WaitList) do
						local _, _, s_dkp, s_raidtime = string.find(v, "(.+)@(.+)");
						local class = "";

						if(zUserClasses[i]~=nil) then
							class = zUserClasses[i];
						end

							local zTmpDate = date("*t", CurrentRaid.JoinedWaitList[i]);
							if(zTmpDate["hour"]<=9) then zTmpDate["hour"] = "0"..zTmpDate["hour"]; end
							if(zTmpDate["min"]<=9) then zTmpDate["min"] = "0"..zTmpDate["min"]; end

							local dTimeNew = format("%s:%s", zTmpDate["hour"],zTmpDate["min"]);

						-------- [ CHECK ONLINE STATUS ] ---------------------------------------------

							LoggedOnPlayer = nil;
							LoggedOnPlayer = DKPMS:IsPlayerOnline(i);

							if(LoggedOnPlayer==nil) then
								LoggedOnPlayer = "<Offline>";
							else
								LoggedOnPlayer = "<Online on: "..LoggedOnPlayer..">";

							end
						-------- [ CHECK ONLINE STATUS ] ---------------------------------------------

						SendChatMessage("<zKP>"..i.." ("..class.."): "..string.format("%.1f",tonumber(s_dkp)).."dkp. Joined: "..dTimeNew.." "..LoggedOnPlayer, WHISPER, nil, arg2);
						counter = counter+1;

					end
					if(counter==0) then
						SendChatMessage("<zKP>Waitlist empty", WHISPER, nil, arg2);
					end
				elseif(string.lower(this_command)=="delete") then
					if(CurrentRaid.WaitList[whichplayer]~=nil) then
						CurrentRaid.WaitList[whichplayer] = nil;
						SendChatMessage("<zKP>You are removed from Waitlist", WHISPER, nil, arg2);
					else
						SendChatMessage("<zKP>You are not in Waitlist", WHISPER, nil, arg2);
					end
				elseif(string.lower(this_command)=="accept") then
					--whichplayer

					if(CurrentRaid.WaitListLastChecked[whichplayer]~=nil) then
						if(time()-CurrentRaid.WaitListLastChecked[whichplayer]<=zKP_WaitListResponseTime) then --20seconds responsetime

							local myInterval = zKP_WaitListInterval;

							if(CurrentRaid.JoinedWaitList[whichplayer]~=nil) then
								--DKPMS:Print((CurrentRaid.WaitListLastChecked[whichplayer]-JoinedWaitList[whichplayer]-zKP_WaitListInterval).." should be removed")

								if((CurrentRaid.WaitListLastChecked[whichplayer]-CurrentRaid.JoinedWaitList[whichplayer]-zKP_WaitListInterval)<100) then
									myInterval = myInterval+(CurrentRaid.WaitListLastChecked[whichplayer]-CurrentRaid.JoinedWaitList[whichplayer]-zKP_WaitListInterval);
								end
							end
							
							--DKPMS:Print(myInterval.." new interval")


							local dkp_to_recieve = (myInterval/60)*(tonumber(zKP_options.frequentDKP)/tonumber(zKP_options.UpdateInterval));
								if(debugging) then
									DKPMS:Print(whichplayer.." +"..dkp_to_recieve.."dkp");
								end
							SendChatMessage("<zKP>You recieve: "..string.format("%.1f",tonumber(dkp_to_recieve)).."dkp", WHISPER, nil, arg2);

							local _, _, s_dkp, s_raidtime = string.find(CurrentRaid.WaitList[whichplayer], "^(.+)@(.+)$");
							if(s_dkp~=nil and s_raidtime~=nil) then

								s_dkp = tonumber(s_dkp)+dkp_to_recieve;
								s_raidtime = tonumber(s_raidtime)+(myInterval/60);

								CurrentRaid.WaitList[whichplayer] = s_dkp.."@"..s_raidtime;
							end				


							CurrentRaid.WaitListLastPassed[whichplayer] = CurrentRaid.WaitListLastChecked[whichplayer]+zKP_WaitListInterval;

							CurrentRaid.WaitListLastChecked[whichplayer] = nil;
						else
							SendChatMessage("<zKP>"..time()-CurrentRaid.WaitListLastChecked[whichplayer]-zKP_WaitListResponseTime.."sec to slow", WHISPER, nil, arg2);
							CurrentRaid.WaitListLastChecked[whichplayer] = nil;

							if(debugging) then
								DKPMS:Print(whichplayer.." to late");
							end

						end
					else
					DKPMS:Print("not allowed");
					end
				end

			return;

		end


	end
  
    --[[ ---------------------------- DKP ADDON SYNC -----------------------------]]
    local prefix = arg1;
    local message = arg2;
    if (event == "CHAT_MSG_ADDON" and prefix == "zKP_Client" and message ~= "DkpLeader" and zKP_raid_running == true) then
        
        local sender = arg4;


        ------------------ [DKP] --------------------
        if( string.find(string.lower(message), "^dkp ([^ ]*)$") ~= nil) then	


            local _, _, check_player = string.find(string.lower(message), "^dkp ([^ ]*)$");

            if(check_player~=nil) then

                    check_player = string.lower(check_player);
                    check_player = string.upper(string.sub(check_player,1,1))..string.sub(check_player,2);

                    if(DKPData["Timbo"][check_player]~=nil) then
                        
                        SendAddonMessage("zKP_Server","<zKP>"..check_player.." DKP:"..DKPMS:GetPlayerDKP(check_player)..". Attendance: "..DKPMS:GetPlayerAttendance(check_player).."%", WHISPER, sender);
                    else                        
                        SendAddonMessage("zKP_Server","<zKP>"..check_player.." doesnt exist", WHISPER, sender);
                    end
                
            end
            return;    
        end
         
    elseif(event == "CHAT_MSG_ADDON" and prefix == "zKP_Client" and message == "DkpLeader"  and zKP_raid_running == true and DKPMS:IsDkpLeaderMasterLooter() == true) then
       SendAddonMessage("zKP_Server", "DkpLeader", "GUILD",nil); 
       DKPMS:Print("SERVER: DkpLeader sendt");
    end
    
end

function DKPMS:IsDkpLeaderMasterLooter()
    
    local numRaidMembers = GetNumRaidMembers();
    local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML;
    
        for	i=1, numRaidMembers  do
        local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i);
            
            
            if (name == zKP_Server_Player_name) then
                if(isML ~= nil) then
                    return true;
                else
                    return false
                end
            end
        end	        
end

--This function returns "player"'s total dkp
function DKPMS:GetPlayerDKP(player)

	-- Check if its an alt of a main, if so then overwrite the player with the main's name
	if(AltList[player]) then
		player = AltList[player];
	end	

    local registrar
	local total = 0;
	for registrar in pairs(DKPData) do	
        local registrardata=DKPData[registrar];

        if(registrardata[player]) then
			total = registrardata[player].DKP + total;
		end	
	end
	return total
end


--This function returns "player"'s attendance
function DKPMS:GetPlayerAttendance(player)

    player = DKPMS:FixName(player);

	-- Check if its an alt of a main, if so then overwrite the check_player with the main's name
	if(AltList[player]) then
		player = AltList[player];
	end	

	local total_user_att = 0;
	local total_raid_att = 0;

	local s_dkp,s_raidtime;

	for RaidDate,RaidArray in DKPMSld:PairsByKeys(PreviusRaid) do

		if(RaidArray["EarnedDKP"][player]~=nil) then
			_, _, s_dkp, s_raidtime = string.find(RaidArray["EarnedDKP"][player], "(.+)@(.+)");
			total_user_att = total_user_att+tonumber(s_raidtime);
		end

		if(RaidArray["EarnedDKP"]["Zmax"]~=nil) then
			_, _, s_dkp, s_raidtime = string.find(RaidArray["EarnedDKP"]["Zmax"], "(.+)@(.+)");
            total_raid_att = total_raid_att+tonumber(s_raidtime);
		end
	end
    
	if(total_user_att > 0 and total_raid_att > 0) then
        local attendance = string.format("%.1f",(total_user_att)/(total_raid_att)*100);
		return attendance;
	else
		return "0";
	end


end